﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Interoperability\DOT\DotHelper_MM.cs
 * Description  :     DOT format helper for MMs
 * Change log   :     -1 Sep 2013:  Initial Version
 * To Do        :     
 ************************************************************************/
using System;
using System.Collections.Generic;
using SMLib.Automata.MM;
using SMLib.Automata.Base;
using SMLib.Utils;

namespace SMLib.Interoperability.DOT
{
    /// <summary>
    /// Dot helper for Mealy machines
    /// </summary>
    public class DotHelper_MM : DotHelper<MealyMachine.Mealy_State,MealyMachine.Mealy_Transition>
    {
        /// <summary>
        /// Write a mealy machine into a file
        /// </summary>
        /// <param name="path">path of file</param>
        /// <param name="mm">the mealy machine</param>
        public static void WriteToDot(string path, MealyMachine mm)
        {
            SMLib.Interoperability.DOT.DotHelper_MM exporter = new SMLib.Interoperability.DOT.DotHelper_MM();
            (exporter as DotHelper<MealyMachine.Mealy_State,MealyMachine.Mealy_Transition>).WriteToDot(path, mm);
        }

        /// <summary>
        /// Read a Mealy machine from a DOT file
        /// </summary>
        /// <param name="inputFile">path of file</param>
        /// <returns>the read mealy machine</returns>
        public static MealyMachine ReadFromDot(string inputFile)
        {
            MealyMachine m = new MealyMachine();
            m.InputAlphabet = new Alphabet();
            m.OutputAlphabet = new Alphabet();

            DotFormat dotReader = new DotFormat();
            string ilbl, olbl;
            foreach (DotFormat.DotTransition tr in dotReader.ReadDotFile(inputFile))
            {
                ilbl = tr.Label.Substring(0, tr.Label.IndexOf("/"));

                if (!m.InputAlphabet.Contains(new StringSymbol(ilbl)))
                    m.InputAlphabet.AddSymbol(new StringSymbol(ilbl));


                olbl = tr.Label.Substring(tr.Label.IndexOf("/") + 1, tr.Label.Length - tr.Label.IndexOf("/") - 1);

                if (!m.OutputAlphabet.Contains(new StringSymbol(olbl)))
                    m.OutputAlphabet.AddSymbol(new StringSymbol(olbl));

                SMLib.Automata.MM.MealyMachine.Mealy_State srcNode = null, dstNode = null;
                foreach (SMLib.Automata.MM.MealyMachine.Mealy_State n in m.GetStates())
                {
                    if (((string)n.Identifier).Equals(tr.Source))
                        srcNode = n;
                    if (((string)n.Identifier).Equals(tr.Destination))
                        dstNode = n;

                    if (dstNode != null && srcNode != null)
                        break;
                }
                if (srcNode == null)
                {
                    srcNode = new SMLib.Automata.MM.MealyMachine.Mealy_State(tr.Source);
                    m.AddState(srcNode);

                    if (tr.Destination == tr.Source)
                        dstNode = srcNode;
                }

                if (dstNode == null)
                {
                    dstNode = new SMLib.Automata.MM.MealyMachine.Mealy_State(tr.Destination);
                    m.AddState(dstNode);
                }

                SMLib.Automata.MM.MealyMachine.Mealy_Transition t = new SMLib.Automata.MM.MealyMachine.Mealy_Transition(new StringSymbol(ilbl), new StringSymbol(olbl));
                t.SetDestination(dstNode);
                srcNode.Transitions.Add(t);
            }
            return m;
        }
    }
}
